package sensor

import (
	"client2/config"
	"fmt"
	"unsafe"
	"strings"
	"strconv"

	"golang.org/x/sys/unix"
	//"log"
)

// 确保 SerialSensorReader 实现 SensorReader 接口
var _ SensorReader = (*SerialSensorReader)(nil)

// SerialSensorReader 串口传感器读取器
type SerialSensorReader struct {
	fd         int
	port       string
	buffer     []byte
	config     *config.SensorConfig
	parser     DataParser
	sensorID   string
	sensorType string
	dataLength int // 新增：每个端口的数据长度
}

// NewSerialSensorReader 创建新的串口传感器读取器
func NewSerialSensorReader(portName string, sensorConfig *config.SensorConfig, parser DataParser, dataLength int) *SerialSensorReader {
	// 从配置中获取传感器类型
	portConfig, exists := sensorConfig.Ports[portName]
	if !exists {
		portConfig = config.SensorPortConfig{
			Type: "unknown",
		}
	}

	return &SerialSensorReader{
		port:       portName,
		config:     sensorConfig,
		parser:     parser,
		buffer:     make([]byte, 0, sensorConfig.BufferSize),
		sensorID:   portConfig.SensorID,
		sensorType: portConfig.Type,
		dataLength: dataLength, // 设置数据长度
	}
}

// NewSerialSensorReaderWithID 创建新的串口传感器读取器（指定传感器ID）
func NewSerialSensorReaderWithID(portName string, sensorConfig *config.SensorConfig, parser DataParser, dataLength int, sensorID string, sensorType string) *SerialSensorReader {
	return &SerialSensorReader{
		port:       portName,
		config:     sensorConfig,
		parser:     parser,
		buffer:     make([]byte, 0, sensorConfig.BufferSize),
		sensorID:   sensorID,   // 使用指定的传感器ID
		sensorType: sensorType, // 使用指定的传感器类型
		dataLength: dataLength, // 设置数据长度
	}
}

// GetName 获取读取器名称
func (r *SerialSensorReader) GetName() string {
	return r.port
}

// Initialize 初始化串口
func (r *SerialSensorReader) Initialize() error {
	fd, err := unix.Open(r.port, unix.O_RDWR|unix.O_NOCTTY, 0)
	if err != nil {
		return fmt.Errorf("打开串口 %s 失败: %v", r.port, err)
	}
	r.fd = fd

	var tty unix.Termios
	_, _, errno := unix.Syscall6(
		unix.SYS_IOCTL,
		uintptr(fd),
		uintptr(unix.TCGETS),
		uintptr(unsafe.Pointer(&tty)),
		0, 0, 0,
	)
	if errno != 0 {
		unix.Close(fd)
		return fmt.Errorf("tcgetattr: %v", errno)
	}

	// 设置波特率
	tty.Cflag &^= unix.CBAUD
	switch r.config.BaudRate {
	case 9600:
		tty.Cflag |= unix.B9600
	case 19200:
		tty.Cflag |= unix.B19200
	case 38400:
		tty.Cflag |= unix.B38400
	case 115200:
		tty.Cflag |= unix.B115200
	default:
		tty.Cflag |= unix.B9600
	}

	// 8位数据位，无奇偶校验，1位停止位
	tty.Cflag &^= unix.PARENB
	tty.Cflag &^= unix.CSTOPB
	tty.Cflag &^= unix.CSIZE
	tty.Cflag |= unix.CS8

	// 非规范模式：VMIN=0, VTIME=1 (0.1秒超时)
	tty.Cc[unix.VMIN] = 0
	tty.Cc[unix.VTIME] = 1

	// 启用接收
	tty.Cflag |= unix.CREAD | unix.CLOCAL

	// 关闭流控
	tty.Cflag &^= unix.CRTSCTS
	tty.Iflag &^= unix.IXON | unix.IXOFF | unix.IXANY

	// 原始模式
	tty.Lflag &^= unix.ICANON | unix.ECHO | unix.ECHOE | unix.ISIG
	tty.Iflag &^= unix.INPCK | unix.ISTRIP | unix.IGNCR | unix.ICRNL | unix.IXON | unix.IXOFF
	tty.Oflag &^= unix.OPOST

	_, _, errno = unix.Syscall6(
		unix.SYS_IOCTL,
		uintptr(fd),
		uintptr(unix.TCSETS),
		uintptr(unsafe.Pointer(&tty)),
		0, 0, 0,
	)
	if errno != 0 {
		unix.Close(fd)
		return fmt.Errorf("tcsetattr: %v", errno)
	}

	return nil
}

// SendHexData 发送自定义十六进制数据的通用函数
func (r *SerialSensorReader) SendHexData(hexString string) error {
	if r.fd == 0 {
		return fmt.Errorf("串口未初始化")
	}

	// 去除空格
	hexString = strings.ReplaceAll(hexString, " ", "")

	// 检查长度是否为偶数
	if len(hexString)%2 != 0 {
		return fmt.Errorf("十六进制字符串长度必须为偶数")
	}

	// 解析十六进制字符串
	data := make([]byte, len(hexString)/2)
	for i := 0; i < len(hexString); i += 2 {
		hexByte := hexString[i : i+2]
		val, err := strconv.ParseUint(hexByte, 16, 8)
		if err != nil {
			return fmt.Errorf("解析十六进制数据失败: %v", err)
		}
		data[i/2] = byte(val)
	}

	// 发送数据
	n, err := unix.Write(r.fd, data)
	if err != nil {
		return fmt.Errorf("发送十六进制数据失败: %v", err)
	}

	if n != len(data) {
		return fmt.Errorf("十六进制数据发送不完整: %d/%d 字节", n, len(data))
	}

	return nil
}

// Read 读取传感器数据
func (r *SerialSensorReader) Read() ([]SensorData, error) {
	// 被动请求式传感器: 在读取前先发送请求命令
	if r.sensorType == "smoke" {
		//fmt.Println("发送自定义十六进制数据...")
		if err := r.SendHexData("FF 01 86 00 00 00 00 00 79"); err != nil {
			fmt.Println("发送自定义数据失败:", err)
		}
		//fmt.Println("自定义数据发送成功")
	}
	if r.sensorType == "conductivity" {
		//fmt.Println("发送自定义十六进制数据...")
		if err := r.SendHexData("A0 00 00 00 00 A0"); err != nil {
			fmt.Println("发送自定义数据失败:", err)
		}
		//fmt.Println("自定义数据发送成功")
	}
	if r.sensorType == "liquid_level" {
		//fmt.Println("发送自定义十六进制数据...")
		if err := r.SendHexData("AA 09 01 03 00 00 00 B7 BB"); err != nil {
			fmt.Println("发送自定义数据失败:", err)
		}
		//fmt.Println("自定义数据发送成功")
	}
	if r.sensorType == "flow" {
		//fmt.Println("发送流速传感器请求命令...")
		if err := r.SendHexData("01 03 00 11 00 01 D4 0F"); err != nil {
			fmt.Println("发送流速请求命令失败:", err)
		}
		//fmt.Println("流速请求命令发送成功")
	}

	buf := make([]byte, r.config.BufferSize)
	n, err := unix.Read(r.fd, buf)
	if err != nil {
		return nil, err
	}

	if n == 0 {
		return nil, nil
	}

	// 将新数据追加到缓冲区
	r.buffer = append(r.buffer, buf[:n]...)

	var results []SensorData

	//log.Printf("raw data:%s", r.buffer)
	// 处理缓冲区中的所有完整帧
	for len(r.buffer) >= r.dataLength { // 使用端口特定的数据长度
		startIndex := -1
		// 查找帧起始符（根据传感器类型）
		for j := 0; j <= len(r.buffer)-r.dataLength; j++ {
			found := false
			switch r.sensorType {
			case "temperature_humidity", "temperature":
				if r.buffer[j] == 'R' {
					startIndex = j
					found = true
				}
			case "co":
				if r.buffer[j] == 0xFF {
					startIndex = j
					found = true
				}
			case "co2":
				if r.buffer[j] == 0x2C {
					startIndex = j
					found = true
				}
			case "smoke":
				if r.buffer[j] == 0xFF {
					startIndex = j
					found = true
				}
			case "conductivity":
				if r.buffer[j] == 0xAA {
					startIndex = j
					found = true
				}
			case "liquid_level":
				if r.buffer[j] == 0xAA {
					startIndex = j
					found = true
				}
			case "flow":
				if r.buffer[j] == 0x01 {
					startIndex = j
					found = true
				}
			default:
				// 默认检测所有可能的起始符
				if r.buffer[j] == 'R' || r.buffer[j] == 'C' || r.buffer[j] == 'S' {
					startIndex = j
					found = true
				}
			}
			if found {
				break // 找到起始符后退出for循环
			}
		}

		if startIndex == -1 {
			// 没有找到有效帧起始符，清空缓冲区
			r.buffer = r.buffer[:0]
			break
		}

		// 检查是否有可能的完整帧
		if startIndex+r.dataLength <= len(r.buffer) { // 使用端口特定的数据长度
			frame := r.buffer[startIndex : startIndex+r.dataLength]
			if r.parser.Validate(frame) {
				sensorData, err := r.parser.Parse(frame)
				if err == nil {
					sensorData.Port = r.port
					sensorData.SensorID = r.sensorID
					sensorData.SensorType = r.sensorType // 设置传感器类型
					results = append(results, *sensorData)
				}
				// 移除已处理的数据
				r.buffer = r.buffer[startIndex+r.dataLength:]
			} else {
				// 无效帧，跳过这个起始符
				r.buffer = r.buffer[startIndex+1:]
			}
		} else {
			// 没有完整帧，保留剩余数据
			if startIndex > 0 {
				r.buffer = r.buffer[startIndex:]
			}
			break
		}
	}

	return results, nil
}

// Close 关闭串口
func (r *SerialSensorReader) Close() error {
	if r.fd != 0 {
		return unix.Close(r.fd)
	}
	return nil
}
